<template>
    <div class="editor-container">
        <div
            ref="editorRef"
            class="monaco-editor"
            style="width: 100%; height: 500px"
        ></div>
        <div v-if="diagnostics.length > 0" class="diagnostic-panel">
            <h4>语法错误 ({{ diagnostics.length }})</h4>
            <ul>
                <li
                    v-for="(item, index) in diagnostics"
                    :key="index"
                    class="diagnostic-item"
                    @pointerdown="goToDiagnostic(item)"
                >
                    <span class="diagnostic-type error">错误</span>
                    <span class="diagnostic-message">{{ item.message }}</span>
                    <span class="diagnostic-location"
                        >第 {{ item.range.startLineNumber }} 行，第
                        {{ item.range.startColumn }} 列</span
                    >
                </li>
            </ul>
        </div>
    </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import 'monaco-editor/esm/vs/basic-languages/lua/lua.contribution';
// import luaParse from 'lua-parse';
import AsaiLuaParse from 'asai-lua-parse';

const props = defineProps({
    value: {
        type: String,
        default: '',
    },
});

const emit = defineEmits(['update:value']);
const editorRef = ref(null);
const code = ref(props.value);
const diagnostics = ref([]);
let editorInstance = null;
let diagnosticCollection = null;

const editorOptions = {
    theme: 'vs-dark',
    language: 'lua',
    fontSize: 18,
    automaticLayout: true,
    wordWrap: 'on',
    minimap: { enabled: false },
};

// 配置Lua语言服务
const configureLuaLanguageService = () => {
    monaco.languages.setLanguageConfiguration('lua', {
        comments: {
            lineComment: '--',
            blockComment: ['--[[', ']]'],
        },
        brackets: [
            ['{', '}'],
            ['[', ']'],
            ['(', ')'],
        ],
        autoClosingPairs: [
            { open: '{', close: '}' },
            { open: '[', close: ']' },
            { open: '(', close: ')' },
            { open: '"', close: '"', notIn: ['string', 'comment'] },
            { open: "'", close: "'", notIn: ['string', 'comment'] },
            { open: '--[[', close: ']]', notIn: ['comment'] },
        ],
        surroundingPairs: [
            { open: '{', close: '}' },
            { open: '[', close: ']' },
            { open: '(', close: ')' },
            { open: '"', close: '"' },
            { open: "'", close: "'" },
        ],
    });

    // diagnosticCollection = monaco.languages.createDiagnosticCollection('lua');
};

// 使用lua-parse校验Lua代码
const validateLuaCode = (code) => {
    try {
        AsaiLuaParse.parse(code, {
                luaVersion: '5.3',
                allowLabel: true,
                locations: true,
                ranges: true,
                comments: false,
        });

        diagnostics.value = [];
        if (diagnosticCollection && editorInstance) {
            diagnosticCollection.set(editorInstance.getModel().uri, []);
        }
    } catch (error) {
        if (error.name === 'SyntaxError') {
            const diagnostic = {
                code: 'syntax-error',
                message: error.message,
                severity: monaco.MarkerSeverity.Error,
                range: {
                    startLineNumber: error.location.start.line,
                    startColumn: error.location.start.column + 1,
                    endLineNumber: error.location.end.line,
                    endColumn: error.location.end.column + 1,
                },
            };

            diagnostics.value = [diagnostic];
            if (diagnosticCollection && editorInstance) {
                diagnosticCollection.set(editorInstance.getModel().uri, [
                    diagnostic,
                ]);
            }
        } else {
            console.error('校验代码时发生未知错误:', error);
        }
    }
};

onMounted(() => {
    configureLuaLanguageService();

    // 直接初始化 Monaco Editor
    editorInstance = monaco.editor.create(editorRef.value, {
        ...editorOptions,
        value: code.value,
    });

    // 监听编辑器内容变化
    editorInstance.onDidChangeModelContent(() => {
        const newCode = editorInstance.getValue();
        code.value = newCode;
        emit('update:value', newCode);
        validateLuaCode(newCode);
    });

    // 初始化时校验一次
    validateLuaCode(code.value);
});

onUnmounted(() => {
    if (editorInstance) {
        editorInstance.dispose();
        editorInstance = null;
    }

    if (diagnosticCollection) {
        diagnosticCollection.dispose();
        diagnosticCollection = null;
    }
});

// 监听外部props变化
watch(
    () => props.value,
    (newValue) => {
        if (newValue !== code.value && editorInstance) {
            editorInstance.setValue(newValue);
            validateLuaCode(newValue);
        }
    }
);

const goToDiagnostic = (item) => {
    if (editorInstance) {
        editorInstance.setPosition({
            lineNumber: item.range.startLineNumber,
            column: item.range.startColumn,
        });
        editorInstance.revealLineInCenter(item.range.startLineNumber);
    }
};
</script>

<style scoped>
.editor-container {
    margin-top: 20px;
    border-radius: 4px;
    overflow: hidden;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.monaco-editor {
    border: 1px solid #e1e4e8;
}

.diagnostic-panel {
    margin-top: 10px;
    padding: 10px;
    border: 1px solid #e1e4e8;
    border-radius: 4px;
    background-color: #f6f8fa;
}

.diagnostic-panel h4 {
    margin: 0 0 10px;
    font-size: 14px;
    font-weight: 600;
}

.diagnostic-panel ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.diagnostic-item {
    margin-bottom: 5px;
    padding: 8px;
    border-radius: 4px;
    background-color: #ffebee;
    color: #b71c1c;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: background-color 0.2s;
}

.diagnostic-item:hover {
    background-color: #ffcdd2;
}

.diagnostic-type {
    font-weight: bold;
    margin-right: 10px;
    padding: 2px 6px;
    border-radius: 3px;
    background-color: #b71c1c;
    color: white;
    font-size: 12px;
}

.diagnostic-message {
    flex: 1;
    margin-right: 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.diagnostic-location {
    font-size: 12px;
    color: #757575;
}
</style>
